import { sequelize, Task, Progress, Answer } from '../models'
import { findOrCreate } from './task'

/**
 * Create a progress for a task
 * Assign group id to task
 * @param {int} taskId
 * @param {int} groupId
 * @param {int} userId
 * @return {object} Progress
 */
export const findOrCreateWithTask = async (taskId, userId) => {
  return sequelize.transaction(async t => {
    let task = await Task.findById(taskId, { transaction: t })
    if (task == null) {
      throw new Error(`${ERRORS.DBERR.ERR_RECORD_NOT_FOUND}`)
    }
    if (!task.name) throw new Error(`no task name!`)
    let progress = await Progress.findOne(
      {
        where: { userId, taskId: task.id }
      },
      { transaction: t }
    )
    if (!progress) {
      if (task.ownerId == userId) {
        throw new Error(`${ERRORS.ERR_NO_PROGRESS_FOR_OWN_TASK}`)
      }
      progress = await Progress.create({
        subTaskCount: task.subTaskCount,
        expireAt: task.expireAt,
        state: 'start',
        userId: userId,
        taskId: task.id,
        type: task.type,
        name: task.name,
        documentId: task.documentId,
        versionId: task.versionId,
        groupId: task.groupId
      }, { transaction: t })

      task.userCount++
      await task.save({ transaction: t })
    }

    return progress
  })
}

/**
 * Find or Create a new Progress instance from a document Id
 * @param {int} documentId
 * @param {int} userId
 * @param {int} groupId
 * @return {object} Progress
 */
export const findOrCreateWithDocument = async (
  documentId,
  userId,
  groupId,
  createdAt
) => {
  let task = await findOrCreate(documentId, userId, groupId, createdAt)
  if (task == null) {
    throw new Error(`${ERRORS.DBERR.ERR_WHEN_INSERT_TO_DB}`)
  }
  return await findOrCreateWithTask(task.id, userId)
}

/**
 * List all progresses for the task
 * Order by updateAt
 * @param {int} taskId
 * @return {array} Progresses
 */
export const findAllTaskProgresses = async taskId => {
  const result = await Progress.findAll({
    where: {
      taskId
    },
    order: [['updatedAt', 'DESC']]
  })
  return result
}

/**
 * List all progresses of the user
 * Order by updateAt
 * @param {int} userId
 * @return {array} Progresses
 */
export const findAllUserProgresses = async (
  userId,
  pageIndex = 0,
  pageSize = 20
) => {
  const result = await Progress.findAndCountAll({
    where: {
      userId,
      isPublished: 1
    },
    offset: pageIndex * pageSize,
    limit: pageSize,
    order: [['createdAt', 'DESC']],
    raw: true
  })
  return result
}

/**
 * Decrease unread count
 * @param {int} progressId
 * @param {int} userId
 * @return {array} Progress
 */
export const readProgress = async (progressId, userId) => {
  return sequelize.transaction(async t => {
    const progress = await Progress.findById(progressId, { transaction: t })
    if (progress) {
      if (progress.unreadCount > 0) {
        // check owner of the task
        let task = await Task.findById(progress.taskId)
        if (task.ownerId == userId) {
          progress.unreadCount = 0
          await Answer.update(
            { unreadCount: 0 },
            { where: { progressId } },
            { transaction: t }
          )
        }
      } else if (progress.unreadCount < 0) {
        if (userId === progress.userId) {
          progress.unreadCount = 0
        }
      }
      await progress.save({ transaction: t, silent: true })
    }
    return progress
  })
}
